<?php
/**
 * 类对象工厂
 * 
 * 可以根据类和参数构造类的对象
 * <code>
 * class X {
 * 	public $a = 1;
 * 	
 * 	public function X($a, $b) {
 * 		var_dump($a);
 * 		var_dump($b);
 * 		echo "<br/>";
 * 	}
 * 	
 * 	public function setA($a) {
 * 		$this->a = $a;
 * 	}
 * }
 * 
 * $x = IObjectFactory::getSingleObject("X", 11, 23);
 * $x->setA(10); // $a --> 10
 * 
 * $x = IObjectFactory::getSingleObject("X", 11, 23); // 不会执行构造函数
 * $x->setA(100);  // $a --> 100
 * 
 * $x = IObjectFactory::getObject("X", 1, 2); // 新的$x，与上面的两个对象无关
 * </code>
 *
 * @version $Id: IObjectFactory.php 323 2008-05-14 05:49:20Z iwind $
 * @package util.core
 */
class IObjectFactory extends IObject {
	private static $map = array();
	
	/**
	 * 取得类的单例
	 * 
	 * 对于同一个类来说，多次调用该方法只返回同一个对象
	 *
	 * @param string $class 类名称
	 * @param mixed $arguments 参数列表
	 * @return object
	 */
	public static function getSingleObject($class, $arguments = null) {
		if (gettype($class) != "string") {
			return;
		}
		if (!array_key_exists($class, self::$map)) {
			$className = native::getRealClassName($class);
			if (!class_exists($className, false)) {
				import($class);
				if (array_key_exists($class, self::$map)) { // 二次检查，防止$class定义文件中调用了getSingleObject
					return self::$map[$class];
				}
			}
			if (!class_exists($className, false)) {
				throw new IException("can not load class '{$class}' from class-path '" . implode(", ", IConfig::getClassPath()) . "'");
			}
			$reflection = new ReflectionClass($className);
			if ($reflection->getConstructor() == null) {
				self::$map[$class] = $reflection->newInstance();
			} else {
				$args = func_get_args();
				array_shift($args);
				self::$map[$class] = $reflection->newInstanceArgs($args);
			}
		}
		return self::$map[$class];
	}
	
	/**
	 * 取得类的实例对象
	 *
	 * @param string $class 类名称
	 * @param mixed $arguments 参数列表
	 * @return object
	 */
	public static function &getObject($class, $arguments = null) {
		import($class);
		$className = native::getRealClassName($class);
		$reflection = new ReflectionClass($className);
		if ($reflection->getConstructor() == null) {
			$object = $reflection->newInstance();
		} else {
			$args = func_get_args();
			array_shift($args);
			$object = $reflection->newInstanceArgs($args);
		}
		self::$map[$class] = $object;
		return $object;
	}
	
	/**
	 * 添加对象引用
	 *
	 * @param IObject $object
	 * @return string
	 * @since 0.1
	 */
	public static function addRef(IObject $object) {
		$refId = $object->refId();
		self::$map[$refId] = $object;
		return $refId;
	}
	
	/**
	 * 取得引用
	 *
	 * @param string $refId 引用ID
	 * @return IObject
	 * @since 0.1
	 */
	public static function getRef($refId) {
		if (array_key_exists($refId, self::$map)) {
			return self::$map[$refId];
		}
		return null;
	}
}

?>